import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import os
from datetime import datetime

def plot_completion_rate_from_existing_data():
    """从现有训练结果绘制误码率与完成率的关系图"""
    
    # 读取现有的Excel数据
    excel_path = r"c:\Users\14159\Desktop\test_code\hewei\results_20250630_211507\training_results_20250701_085812.xlsx"
    
    try:
        df = pd.read_excel(excel_path)
        print(f"成功读取数据文件: {excel_path}")
        print(f"数据列: {list(df.columns)}")
        print(f"数据形状: {df.shape}")
        print("\n前几行数据:")
        print(df.head())
        
        # 检查是否包含完成率数据
        if 'success_rate' in df.columns:
            # 如果已有完成率数据，直接使用
            ber_values = df['ber'].values
            success_rates = df['success_rate'].values
            avg_returns = df['avg_return'].values
            
        elif 'avg_return' in df.columns:
            # 如果只有平均回报，需要从保存的模型重新评估获取完成率
            print("\n数据中没有完成率信息，需要从保存的模型重新评估...")
            
            # 这里我们可以创建一个评估脚本
            create_evaluation_script()
            return
            
        else:
            print("数据格式不符合预期，请检查Excel文件内容")
            return
            
        # 绘制完成率曲线
        plt.figure(figsize=(15, 10))
        
        # 子图1：误码率 vs 完成率（对数坐标）
        plt.subplot(2, 3, 1)
        plt.semilogx(ber_values, success_rates, 'bo-', linewidth=2, markersize=8)
        plt.xlabel('误码率 (BER)')
        plt.ylabel('完成率 (Success Rate)')
        plt.title('误码率对完成率的影响（对数坐标）')
        plt.grid(True, alpha=0.3)
        plt.ylim(0, 1.05)
        
        # 子图2：误码率 vs 完成率（线性坐标）
        plt.subplot(2, 3, 2)
        plt.plot(ber_values, success_rates, 'ro-', linewidth=2, markersize=8)
        plt.xlabel('误码率 (BER)')
        plt.ylabel('完成率 (Success Rate)')
        plt.title('误码率对完成率的影响（线性坐标）')
        plt.grid(True, alpha=0.3)
        plt.ylim(0, 1.05)
        
        # 子图3：误码率 vs 平均回报
        plt.subplot(2, 3, 3)
        plt.semilogx(ber_values, avg_returns, 'go-', linewidth=2, markersize=8)
        plt.xlabel('误码率 (BER)')
        plt.ylabel('平均回报')
        plt.title('误码率对平均回报的影响')
        plt.grid(True, alpha=0.3)
        
        # 子图4：完成率下降百分比
        max_success_rate = max(success_rates)
        completion_degradation = [(max_success_rate - rate) / max_success_rate * 100 for rate in success_rates]
        
        plt.subplot(2, 3, 4)
        plt.semilogx(ber_values, completion_degradation, 'mo-', linewidth=2, markersize=8)
        plt.xlabel('误码率 (BER)')
        plt.ylabel('完成率下降百分比 (%)')
        plt.title('相对于最佳完成率的下降程度')
        plt.grid(True, alpha=0.3)
        
        # 子图5：双轴图：同时显示完成率和平均回报
        plt.subplot(2, 3, 5)
        ax1 = plt.gca()
        color = 'tab:red'
        ax1.set_xlabel('误码率 (BER)')
        ax1.set_ylabel('完成率', color=color)
        line1 = ax1.semilogx(ber_values, success_rates, 'o-', color=color, linewidth=2, markersize=8)
        ax1.tick_params(axis='y', labelcolor=color)
        ax1.set_ylim(0, 1.05)
        
        ax2 = ax1.twinx()
        color = 'tab:blue'
        ax2.set_ylabel('平均回报', color=color)
        line2 = ax2.semilogx(ber_values, avg_returns, 's-', color=color, linewidth=2, markersize=8)
        ax2.tick_params(axis='y', labelcolor=color)
        
        plt.title('误码率对完成率和回报的综合影响')
        ax1.grid(True, alpha=0.3)
        
        # 子图6：数据表格
        plt.subplot(2, 3, 6)
        plt.axis('tight')
        plt.axis('off')
        
        # 创建表格数据
        table_data = []
        for i in range(len(ber_values)):
            table_data.append([
                f"{ber_values[i]:.6f}",
                f"{success_rates[i]:.3f}",
                f"{avg_returns[i]:.2f}",
                f"{completion_degradation[i]:.1f}%"
            ])
        
        table = plt.table(cellText=table_data,
                         colLabels=['误码率', '完成率', '平均回报', '完成率下降'],
                         cellLoc='center',
                         loc='center')
        table.auto_set_font_size(False)
        table.set_fontsize(8)
        table.scale(1.2, 1.5)
        plt.title('详细结果表格')
        
        plt.tight_layout()
        
        # 保存图表
        timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
        plot_path = f"completion_rate_analysis_{timestamp}.png"
        plt.savefig(plot_path, dpi=300, bbox_inches='tight')
        plt.show()
        
        print(f"\n完成率分析图表已保存到: {plot_path}")
        
        # 打印统计信息
        print(f"\n=== 完成率统计分析 ===")
        print(f"误码率范围: {min(ber_values):.6f} - {max(ber_values):.6f}")
        print(f"完成率范围: {min(success_rates):.3f} - {max(success_rates):.3f}")
        print(f"平均完成率: {np.mean(success_rates):.3f}")
        print(f"完成率标准差: {np.std(success_rates):.3f}")
        print(f"最大完成率下降: {max(completion_degradation):.1f}%")
        
    except FileNotFoundError:
        print(f"找不到文件: {excel_path}")
        print("请确认文件路径是否正确")
    except Exception as e:
        print(f"读取数据时出错: {e}")

def create_evaluation_script():
    """创建从保存模型评估完成率的脚本"""
    script_content = '''
import sys
sys.path.append(r"c:\\Users\\14159\\Desktop\\test_code\\hewei\\maddpg_-uav\\MADDPG-master")

import torch
import numpy as np
import pandas as pd
from runner import Runner
from common.arguments import get_args
from environment.encirclement_env import EncirclementEnv
import os

def evaluate_saved_models():
    """评估已保存的模型获取完成率数据"""
    
    # 获取参数
    args = get_args()
    args.evaluate = True
    args.evaluate_episodes = 100  # 增加评估回合数以获得更准确的完成率
    
    # 初始化环境
    env = EncirclementEnv(args)
    
    # 误码率列表
    ber_values = np.logspace(-3, -2, 11)
    
    results = []
    model_base_path = r"c:\\Users\\14159\\Desktop\\test_code\\hewei\\results_20250630_223917"
    
    for ber in ber_values:
        model_path = os.path.join(model_base_path, f"model_ber_{ber:.6f}")
        
        if os.path.exists(model_path):
            print(f"\\n评估误码率 {ber:.6f} 的模型...")
            
            # 创建runner
            runner = Runner(args, env)
            runner.bit_flip_probability = ber
            
            # 加载模型
            try:
                for j, agent in enumerate(runner.agents):
                    actor_path = os.path.join(model_path, f"actor_agent_{j}.pth")
                    critic_path = os.path.join(model_path, f"critic_agent_{j}.pth")
                    
                    if os.path.exists(actor_path) and os.path.exists(critic_path):
                        agent.policy.actor_network.load_state_dict(torch.load(actor_path))
                        agent.policy.critic_network.load_state_dict(torch.load(critic_path))
                        print(f"已加载智能体 {j} 的模型")
                
                # 评估模型
                avg_return, success_rate = runner.evaluate()  # 需要修改evaluate方法返回两个值
                
                results.append({
                    'ber': ber,
                    'avg_return': avg_return,
                    'success_rate': success_rate,
                    'training_episodes': 2000  # 假设的训练回合数
                })
                
                print(f"误码率 {ber:.6f}: 平均回报={avg_return:.2f}, 完成率={success_rate:.3f}")
                
            except Exception as e:
                print(f"加载或评估模型时出错: {e}")
        else:
            print(f"找不到误码率 {ber:.6f} 的模型路径: {model_path}")
    
    # 保存结果
    if results:
        df = pd.DataFrame(results)
        output_path = "evaluation_results_with_completion_rate.xlsx"
        df.to_excel(output_path, index=False)
        print(f"\\n评估结果已保存到: {output_path}")
        
        # 调用绘图函数
        plot_completion_rate_from_results(results)
    else:
        print("没有成功评估任何模型")

def plot_completion_rate_from_results(results):
    """从评估结果绘制完成率图表"""
    # 这里可以复用上面的绘图代码
    pass

if __name__ == "__main__":
    evaluate_saved_models()
'''
    
    with open("evaluate_completion_rate.py", "w", encoding="utf-8") as f:
        f.write(script_content)
    
    print("\n已创建评估脚本: evaluate_completion_rate.py")
    print("您可以运行此脚本来从保存的模型获取完成率数据")

if __name__ == "__main__":
    plot_completion_rate_from_existing_data()